<template>
  <lay-card style="width: 99%;min-width: 600px">
    <!-- 选择规则描述方式 -->
    <lay-line v-if="mode !=='field'"></lay-line>
    <lay-row space="5" size="md" v-if="mode !=='field'">
      <lay-col :md="firstColWidth"></lay-col>
      <lay-col md="3">
        <lay-dropdown updateAtScroll>
          <p style="margin-top: 10px;float: right;margin-right: 10px">
            <lay-icon type="layui-icon-set" size="xs" style="font-size: 10px;"></lay-icon>方式
          </p>
          <template #content>
            <lay-dropdown-menu>
              <lay-dropdown-menu-item :key="item" v-for="item in ruleTypeList">
                <lay-checkbox
                    name="like"
                    skin="primary"
                    v-model="item.vision"
                    value="1"
                    :label="item.name"
                ></lay-checkbox>
              </lay-dropdown-menu-item>
            </lay-dropdown-menu>
          </template>
        </lay-dropdown>
      </lay-col>
      <lay-col md="16">
        <a v-for="item in ruleTypeListNew">
          <lay-radio
            v-if="item.vision"
            :value="item.id"
            v-model="rule_expression_type"
            size="xs"
            style="height: 80px"
            :disabled="disable"
          >
            {{ item.name }}
          </lay-radio>
        </a>
      </lay-col>
      <lay-col md="2" v-if="addMode">
        <lay-button
          size="sm"
          class="btn2"
          @click="setParentRule"
          type="normal"
          style="margin-top: 10px"
        >确定</lay-button>
      </lay-col>
    </lay-row>
    <lay-line></lay-line>
    <lay-scroll :height="scrollHeight" style="margin-top: 10px;margin-bottom: 10px">
      <!-- 内置规则固化，规则配置 -->
      <lay-row space="5" :style="{'display': rule_expression_type == 0 ? 'block' : 'none', 'min-width': '700px'}">
        <lay-col :md="firstColWidth"></lay-col>
        <lay-col md="2">
          <p style="margin-top: 10px;float: right;margin-right: 10px">规则</p>
        </lay-col>
        <lay-col md="16">
          <TagInput
            :mode="mode"
            v-model:rawTags="targetRule"
            @setValue="setTagInput"
            :max="1"
            :paramWidth="ruleParamsWidth"
            :outParamsFlag=true
          ></TagInput>
        </lay-col>
        <lay-col md="1" v-if="mode === 'field'"></lay-col>
        <lay-col md="3" v-if="mode === 'field'">
          <lay-button size="sm" type="normal" @click="setParentRule" style="margin-left: 20px">确定</lay-button>
        </lay-col>
      </lay-row>
      <!-- 判断表达式，规则配置 -->
      <lay-row space="20" :style="{'display': rule_expression_type == 1 ? 'block' : 'none', 'min-width': '900px'}">
        <lay-col :md="firstColWidth"></lay-col>
        <lay-col md="22">
          <lay-row space="10">
            <lay-col md="2">
              <p style="margin-top: 10px;float: right;margin-right: 10px">表达式</p>
            </lay-col>
            <lay-col md="18">
              <TagInput
                v-model:rawTags="expression_left"
                @setValue="setExpressionLeft"
                :paramWidth="ruleParamsWidth"
              ></TagInput>
            </lay-col>
<!--            <lay-col md="2">-->
<!--               <lay-select v-model="expression_flag" size="sm" placeholder="" style="width: 100%">-->
<!--                <lay-select-option :value="item" :label="item" v-for="item in operators_logic"></lay-select-option>-->
<!--              </lay-select>-->
<!--            </lay-col>-->
<!--            <lay-col md="8">-->
<!--              <TagInput -->
<!--                v-model:rawTags="expression_right" -->
<!--                @setValue="setExpressionRight"-->
<!--                :paramWidth="ruleParamsWidth"-->
<!--              ></TagInput>-->
<!--            </lay-col>-->
          </lay-row>
        </lay-col>
      </lay-row>
      <!-- 条件表达式，规则配置-->
      <lay-row space="1" :style="{'display': rule_expression_type == 2 ? 'block' : 'none', 'min-width': '900px'}">
        <lay-col :md="firstColWidth"></lay-col>
        <lay-col md="22">
          <lay-row space="5" v-for="(item, index) in caseExpression" :key="item.id">
            <div v-if="item.id !== 'default'">
              <lay-col md="2"><span class="condition-style">case {{index+1}} when</span></lay-col>
              <lay-col md="10">
                <TagInput
                  v-model:rawTags="item.caseParams"
                  :id="item.id"
                  @setValue="setCaseValue"
                  :paramWidth="ruleParamsWidth"
                ></TagInput>
              </lay-col>
              <lay-col md="1"><span class="condition-style">then</span></lay-col>
              <lay-col md="7">
                <TagInput
                  v-model:rawTags="item.thenParams"
                  :id="item.id"
                  @setValue="setThenValue"
                  :paramWidth="ruleParamsWidth"
                ></TagInput>
              </lay-col>
              <lay-col md="4">
                <lay-button size="sm" style="margin-left: 10px;margin-top: 5px" @click="addCase(index)">
                  <lay-icon type="layui-icon-addition"></lay-icon>
                </lay-button>
                <lay-button size="sm" style="margin-top: 5px" @click="deleteCase(index)">
                  <lay-icon type="layui-icon-subtraction"></lay-icon>
                </lay-button>
              </lay-col>
            </div>
            <div v-else>
              <lay-col md="2"><span class="condition-style">default</span></lay-col>
              <lay-col md="10">
                <TagInput
                  v-model:rawTags="item.thenParams"
                  :id="item.id"
                  @setValue="setThenValue"
                  :paramWidth="ruleParamsWidth"
                ></TagInput>
              </lay-col>
            </div>
          </lay-row>
        </lay-col>
      </lay-row >
      <!-- 正则表达式，配置规则 -->
      <lay-row space="1" :style="{'display': rule_expression_type == 3 ? 'block' : 'none'}">
        <lay-col :md="firstColWidth"></lay-col>
        <lay-col md="12">
          <lay-form-item label="正则表达式">
            <lay-input
                placeholder="输入正则表达式，例如：\d{6}"
                v-model="repExpression"
                allow-clear
                :disabled="disable"
            ></lay-input>
          </lay-form-item>
        </lay-col>
        <lay-col md="2"><lay-icon type="layui-icon-help-circle" @click="regTest"></lay-icon></lay-col>
      </lay-row>
      <!-- python函数，定义规则 -->
      <lay-row space="1" :style="{'display': rule_expression_type == 4 ? 'block' : 'none'}">
        <lay-col :md="firstColWidth"></lay-col>
        <lay-col md="4"></lay-col>
        <lay-col md="12">
          <lay-textarea
              placeholder="输入python函数"
              v-model="scriptPython"
              style="height: 250px"
              :disabled="disable"
          >
          </lay-textarea>
        </lay-col>
      </lay-row>
      <!-- 枚举值 -->
      <lay-row space="1" :style="{'display': rule_expression_type == 5 ? 'block' : 'none'}">
        <lay-col :md="firstColWidth"></lay-col>
        <lay-col md="2">
          <p style="margin-top: 6px;float: right;margin-right: 10px">枚举值</p>
        </lay-col>
        <lay-col md="20">
          <lay-row space="2" v-for="(item, index) in enums" :key="item.no">
            <lay-col md="6">
              <lay-input
                size="sm"
                placeholder="请输入"
                v-model="item.value"
                allow-clear
              ></lay-input>
            </lay-col>
            <lay-col md="8">
                <lay-button size="sm" style="margin-left: 10px;" @click="addEnum(index)">
                  <lay-icon type="layui-icon-addition"></lay-icon>
                </lay-button>
                <lay-button size="sm" @click="deleteEnum(index)">
                  <lay-icon type="layui-icon-subtraction"></lay-icon>
                </lay-button>
              </lay-col>
          </lay-row>
        </lay-col>
      </lay-row>
      <!-- SQL语句 -->
      <lay-row space="1" :style="{'display': rule_expression_type == 6 ? 'block' : 'none'}">
        <lay-col :md="firstColWidth"></lay-col>
        <lay-col md="2">
          <p style="margin-top: 10px;float: right;margin-right: 10px">SQL</p>
        </lay-col>
        <lay-col md="20">
          <lay-select size="sm" placeholder="请选择选取方式" v-model="sql_param">
              <lay-select-option value="first" label="first"></lay-select-option>
              <lay-select-option value="random" label="random"></lay-select-option>
          </lay-select>
          <lay-textarea
            placeholder="请输入sql语句"
            v-model="sql_data"
          ></lay-textarea>
        </lay-col>
      </lay-row>
    </lay-scroll>
    <lay-line></lay-line>
  </lay-card>
</template>

<script lang="ts">
import RulesTree from "./RulesTree.vue";
import TagInput from "./TagInput.vue";

export default {
    name: "RuleDescription",
    components: {
      RulesTree,
      TagInput
    }
}
</script>


<script lang="ts" setup>
import {h, onBeforeMount, reactive, ref, watch} from "vue";
import {layer} from "@layui/layer-vue";
import {queryTreeRulesApi} from "../../api/module/rule";
// 引入 nanoid
import { nanoid } from 'nanoid';

// 组件入参 mode：应用场景模式，describe_mode：规则描述方式，content：规则内容
const {disabled, mode, describe_mode, content, setDefaultRule, cancelSetRule, scrollHeight} = defineProps({
    disabled: {type: Boolean, default: false},
    mode: {type: String, default: 'rule'},      // 可选值有 field， rule， scene
    describe_mode:　{type: Number, default: 0},
    content: {type: Object, default: ref({})},
    setDefaultRule: {type: Function},
    cancelSetRule: {type: Function},
    scrollHeight: {type: String, default: '162px'}
})

const emitMethods = defineEmits(["setRuleContent", "cancelSetRule"])

const disable = ref(false);
const ruleParamsWidth = ref(8);  //内置规则参数宽度调整 6或12

// 组件创建前要加载的函数
onBeforeMount(() => {
    disable.value = disabled;
    setInitParams();
    setContent(describe_mode, content);
});

// 根据组件在不同页面被打开应用的场景类型，设置初始化参数
const setInitParams = () => {
    console.log('RuleDescription mode :' + mode)
    if (mode === 'scene') {
        addMode.value = true;
        ruleParamsWidth.value = 12;
        fieldVision.value = true;
        ruleTypeList.value = ruleTypeListScene.value;
        rule_expression_type.value = 5;
        firstColWidth.value = 0;
    }else if(mode === 'rule'){
        fieldVision.value = false;
        ruleTypeList.value = ruleTypeListRule.value;
        rule_expression_type.value = describe_mode;
        ruleParamsWidth.value = 8;
        firstColWidth.value = 1;
    }else if(mode === 'field'){
        addMode.value = true;
        ruleParamsWidth.value = 12;
        fieldVision.value = false;
        ruleTypeList.value = ruleTypeListField.value;
        rule_expression_type.value = 0;
        firstColWidth.value = 0;
    }else {
        ruleTypeList.value = ruleTypeListAll.value;
        rule_expression_type.value = 0;
    }
    targetRule.value.pop();
    ruleTypeListNew.value = ruleTypeList.value;
};

// 设置参数
const setContent = (describe_mode: number, content: any) => {
  console.log('setContent:', describe_mode, content)
  rule_expression_type.value = describe_mode;
  if(content !== null){
    switch (describe_mode) {
    case 0:  //内置规则参数固化
      if(content.ruleParams) {
        targetRule.value = content.ruleParams;
      }
      break;
    case 1:  // 判断表达式
      if(content.leftParams || content.midParams || content.rightParams) {
        expression_left.value = content.leftParams;
        expression_flag.value = content.midParams.value;
        expression_right.value = content.rightParams;
      }
      break;
    case 2:  //条件表达式
      if(content.ruleParams) {
        caseExpression.value = content.ruleParams;
      }
      break;
    case 3:  //正则表达式
      if(content.ruleParams) {
        repExpression.value = content.ruleParams[0].value;
      }
      break;
    case 4:  //自定义 python 函数
      scriptPython.value = content.ruleParams.value;
      break;
    case 5:  // 枚举值
      if(content.ruleParams){
        enums.value = content.ruleParams;
      }
      if(enums.value.length === 0){
        enums.value = [{value: '', no: '0'}]
      }
      break;
    case 6:  // SQL语句
      if(content.ruleParams) {
        sql_param.value = content.ruleParams[0].param;
        sql_data.value = content.ruleParams[0].value;
      }
      break;
    default:  //默认设置
      break;
    }
  }
}

// 定义应用场景显示的字段
const fieldVision = ref(false);
const firstColWidth = ref(1);
const addMode = ref(false);


// 规则表达式描述类型
const rule_expression_type = ref(0);

const ruleTypeListAll =  ref([
    {id: 0, name: '规则参数固化', vision: true},
    {id: 1, name: '表达式', vision: true},
    {id: 2, name: '条件表达式', vision: true},
    {id: 3, name: '正则表达式', vision: true},
    {id: 4, name: '自定义py函数', vision: true},
]);

const ruleTypeListField =  ref([
    {id: 0, name: '规则参数固化'},
]);

const ruleTypeListScene =  ref([
    {id: 0, name: '关联规则或表字段', vision: true},
    {id: 5, name: '枚举值', vision: true},
    {id: 6, name: 'SQL语句', vision: true},
    {id: 3, name: '正则表达式', vision: false},
    {id: 1, name: '表达式', vision: true},
    {id: 2, name: '条件表达式', vision: false},
]);

const ruleTypeListRule =  ref([
    {id: 5, name: '枚举值', vision: true},
    {id: 6, name: 'SQL语句', vision: true},
    {id: 3, name: '正则表达式', vision: true},
    {id: 0, name: '规则参数固化', vision: true},
    {id: 1, name: '表达式', vision: true},
    {id: 2, name: '条件表达式', vision: true},
]);

// 规则描述方式，可切换的值列表。有3种场景应用，如上rule，scene，field
const ruleTypeList: any = ref([]);
const ruleTypeListNew: any = ref([]);

watch(ruleTypeList.value, (newVal, oldVal)=>{
  const temp_list= ref([]);
  newVal.forEach((unit: any)=>{
    temp_list.value.push(unit);
  })
  ruleTypeListNew.value = temp_list.value;
},{immediate: true})

const setTagInput = (data: any) => {
  console.log('TagInput:', data)
  targetRule.value = data;
};


// 内置规则描述内容 函数以及入参
// {rule_id: 'A001', rule_name: '国家', rule_func: 'get_country',
const ruleList = ref([]);
const targetRule: any = ref([]);

const setParentRule = () => {
  console.log('setParentRule: ');
  const targetRuleContent = submitContent()
  const res = setDefaultRule(targetRuleContent);
  if(res){
    layer.msg('设置成功', { time: 1000, icon: 1 })
  }
};


// ------------------- 判断表达式 -----------------
const editConditionRef = ref<any>();

const expression_left: any = ref([]);
const expression_flag = ref('=');
const expression_right: any = ref([]);

const operators_logic = ref(['>', '<', '=', 'in']);

const setExpressionLeft = (data: any) => {
    expression_left.value = data;
};

const setExpressionRight = (data: any) => {
    expression_right.value = data;
};

// ------------------- 正则表达式 --------------------
const repExpression = ref('');

const regTest = () => {
  layer.open({
      type: "iframe",
      title: "远程页面",
      area: ['60%','80%'],
      content: "http://www.yunjson.com/reg/"
  })
}

// ---------- 条件表达式 -------------------
// [
//   {id: 1, case: ['a', '<', '1'], then: ['8']},
//   {id: 2, case: ['1', '<', 'a', '<', '10'], then: ['9']},
//   {id: 3, case: ['a', '>', '10'], then: ['10']},
//   {id: 0, case: ['0'], then: ['0']}
// ]
const caseExpression: any = ref([
  {id: 'no.01', caseParams: [], thenParams: []},
  {id: 'default', caseParams: [], thenParams: []}
]);

const addCase = (index: number) => {
  const caseNum = nanoid();
  caseExpression.value.splice(index+1, 0, {id: caseNum, caseParams: [], thenParams: []})
};

const deleteCase = (index: number) => {
  if(index > 0) {
    caseExpression.value.splice(index, 1)
  }else {
    layer.msg('不能都删除了，至少保留一个！')
  }
};

const setCaseValue = (no: string, data: any) => {
  caseExpression.value.forEach((unit: any)=>{
    console.log('index:', unit)
    if(unit.id === no){
      unit.caseParams = data;
    }
  })
};

const setThenValue = (no: string, data: any) => {
  caseExpression.value.forEach((unit: any)=>{
    console.log('index:', unit)
    if(unit.id === no){
      unit.thenParams = data;
    }
  })
};

// -------------- 定义Python函数的高阶操作
const scriptPython = ref("#!/usr/bin/python3\n" +
  "# -*- coding:utf-8 -*-\n" +
  "\"\"\"\"\n" +
  "@Author: lijk34925\n" +
  "@File: FileName.py\n" +
  "\"\"\"\n\n"+
  "def functionName(value, args=None):\n" +
  "    pass\n" +
  "    return result\n"
);


// ----------- 枚举值 describe_mode=5 ---------------------
const enums: any = ref([{value: '', no: '0'}]);

const addEnum = (index: number) => {
  const newValue = {no: nanoid(), value: ''};
  enums.value.splice(index+1, 0, newValue);
};

const deleteEnum = (index: number) => {
  enums.value.splice(index, 1);
};

// ------------ sql ---------------
const sql_param = ref('first');
const sql_data = ref('');


// ------------ 规则内容，提交父组件 -----------------------

const getValues = function (list: [], split: string = ' ') : string {
  console.log("getValues list:" + list)
  const result = ref('');
  if(list.length>0){
    list.forEach((unit: any, index)=>{
      if(index>0){
        result.value += split + unit.value;
      }else {
        result.value += unit.value;
      }
    })
  }
  console.log("getValues result:" + result.value)
  return result.value;
}

const submitContent = () => {
  // 规则描述内容
  const ruleContent = reactive({
    describe_mode: 0,
    content: {
      defaultRule: '',
      ruleParams: [], // 正则表达式，枚举值，SQL，规则固化，条件表达式
      leftParams: [], // 判断表达式，左侧的值
      midParams: [],  // 判断表达式，中间的判断符号
      rightParams: [] // 判断表达式，右侧的值
    }
  });
  switch (rule_expression_type.value) {
    case 0:  //内置规则参数固化
      ruleContent.describe_mode = 0;
      ruleContent.content.ruleParams = targetRule.value;
      ruleContent.content.defaultRule = getValues(targetRule.value);
      break;
    case 1:  //判断表达式
      ruleContent.describe_mode = 1;
      ruleContent.content.leftParams = expression_left.value;
      const ruleOne: any = reactive([{value: expression_flag.value}]);
      ruleContent.content.midParams = ruleOne;
      ruleContent.content.rightParams = expression_right.value;
      ruleContent.content.defaultRule += getValues(expression_left.value);
      ruleContent.content.defaultRule += ' ' + expression_flag.value;
      ruleContent.content.defaultRule += getValues(expression_right.value);
      break;
    case 2:  //条件表达式
      ruleContent.describe_mode = 2;
      ruleContent.content.ruleParams = caseExpression.value;
      const num = caseExpression.value.length;
      ruleContent.content.defaultRule = num.toString() + '个条件表达式';
      break;
    case 3:  //正则表达式
      ruleContent.describe_mode = 3;
      const ruleExp: any = reactive([{value: repExpression.value}]);
      ruleContent.content.ruleParams = ruleExp;
      ruleContent.content.defaultRule = repExpression.value;
      break;
    case 4:  //自定义 python 函数
      ruleContent.describe_mode = 4;
      const script: any = reactive([{value: scriptPython.value}]);
      ruleContent.content.ruleParams = script;
      ruleContent.content.defaultRule = scriptPython.value;
      break;
    case 5:  // 枚举值
      ruleContent.describe_mode = 5;
      ruleContent.content.ruleParams = enums.value;
      ruleContent.content.defaultRule += getValues(enums.value, ',');
      break;
    case 6:  // SQL语句
      ruleContent.describe_mode = 6;
      const sqlOne:any = reactive([{param: sql_param.value, value: sql_data.value}]);
      ruleContent.content.ruleParams = sqlOne;
      ruleContent.content.defaultRule = sql_data.value;
      break;
    default:  //默认设置
      ruleContent.describe_mode = -1;
      break;
  }
  console.log('submitContent :　', ruleContent)
  return ruleContent;
}

// 第二部：暴露方法
defineExpose({
    submitContent,
    setContent
})
</script>

<style scoped>
.function-prepend {
    width: 100px;
}
.condition-style {
  margin-left: 10px;
  margin-top: 10px;
}
</style>